import * as fs from 'node:fs'
import * as path from 'node:path'

/* 
使用示例
set用法
// const cacheDir = path.join(__dirname, 'cache')
    // const cache = new JSONCache(cacheMusicDir) // 缓存文件将存储在 ./data-cache 目录下

     try {
      // 存储或更新缓存
      await cache.set('localMusicCache', musicList)
      console.log('用户数据已缓存')
    } catch (error) {
      console.error('缓存用户数据失败:', error)
    } 

get用法
const cache = new JSONCache(cacheMusicDir)
    try {
      const data = await cache.get('metadata')
      return data
    } catch (error) {
      console.error('获取缓存数据失败:', error)
      return null
    }
*/
class JSONCache {
  /**
   * 创建 JSON 缓存实例
   * @param {string} cacheDir - 缓存文件存储的目录
   */
  private cacheDir: string

  constructor(cacheDir) {
    this.cacheDir = path.resolve(cacheDir)
  }

  /**
   * 确保缓存目录存在
   * @private
   */
  async _ensureCacheDir() {
    console.log('缓存目录', this.cacheDir)
    try {
      console.log('进来了')

      await fs.promises.mkdir(this.cacheDir, { recursive: true })
    } catch (error: any) {}
  }

  /**
   * 为缓存项生成文件路径
   * @param {string} key - 缓存键
   * @returns {string} 文件路径
   * @private
   */
  _getFilePath(key) {
    // 简单地将 key 转换为安全的文件名
    const safeKey = key.replace(/[^a-zA-Z0-9_-]/g, '_')
    return path.join(this.cacheDir, `${safeKey}.json`)
  }

  /**
   * 将 JSON 数据存入缓存 (永久存储)
   * @param {string} key - 缓存键
   * @param {any} data - 要缓存的 JSON 兼容数据
   * @returns {Promise<void>}
   */
  async set(key, data) {
    if (!key) {
      throw new Error('缓存键不能为空')
    }

    const filePath = this._getFilePath(key)

    try {
      // 确保目录已存在
      // await this._ensureCacheDir()
      await fs.promises.mkdir(this.cacheDir, { recursive: true })
      console.log('缓存目录', this.cacheDir)

      // 序列化数据
      const jsonData = JSON.stringify(data, null, 2) // 格式化输出便于查看
      await fs.promises.writeFile(filePath, jsonData, 'utf8')
      console.log(`JSON 缓存已设置/更新: ${key}`)
    } catch (error: any) {
      console.error(`设置 JSON 缓存失败 (${key}):`, error.message)
      throw error
    }
  }

  /**
   * 从缓存中读取 JSON 数据
   * @param {string} key - 缓存键
   * @returns {Promise<any|null>} 缓存的 JSON 数据 或 null (未找到)
   */
  async get(key) {
    if (!key) {
      return null
    }

    const filePath = this._getFilePath(key)

    try {
      console.log('缓存文件路径', filePath)

      const fileContent = await fs.promises.readFile(filePath, 'utf8')
      // console.log('缓存文件内容', fileContent)
      const data = JSON.parse(fileContent)
      console.log(`JSON 缓存已获取: ${key}`)
      return data
    } catch (error: any) {
      if (error.code === 'ENOENT') {
        // 文件不存在
        return null
      } else if (error instanceof SyntaxError) {
        // JSON 格式错误
        console.warn(`JSON 缓存文件损坏 (${key}), 将被删除`)
        await this.delete(key) // 自动清理损坏的文件
        return null
      } else {
        console.error(`获取 JSON 缓存失败 (${key}):`, error.message)
        throw error
      }
    }
  }

  /**
   * 删除指定的缓存项
   * @param {string} key - 缓存键
   * @returns {Promise<void>}
   */
  async delete(key) {
    if (!key) {
      return
    }

    const filePath = this._getFilePath(key)

    try {
      await fs.promises.unlink(filePath)
      console.log(`JSON 缓存已删除: ${key}`)
    } catch (error: any) {
      if (error.code !== 'ENOENT') {
        // 忽略文件不存在错误
        console.error(`删除 JSON 缓存失败 (${key}):`, error.message)
        throw error
      }
    }
  }

  /**
   * 清理所有缓存项
   * @returns {Promise<void>}
   */
  async clear() {
    try {
      const files = await fs.promises.readdir(this.cacheDir)
      const jsonFiles = files.filter((file) => file.endsWith('.json'))

      if (jsonFiles.length === 0) {
        console.log('没有 JSON 缓存文件可清除')
        return
      }

      await Promise.all(
        jsonFiles.map((file) =>
          fs.promises.unlink(path.join(this.cacheDir, file)).catch((err) => {
            if (err.code !== 'ENOENT') throw err
          })
        )
      )

      console.log(`所有 JSON 缓存已清除 (${jsonFiles.length} 个文件)`)
    } catch (error: any) {
      console.error('清除所有 JSON 缓存失败:', error.message)
      throw error
    }
  }
}

export { JSONCache }
